////////////////////////////////////////////////////////////////////////////////
//
//  MICROSOFT CORPORATION
//  Copyright (c) Microsoft Corporation.
//  All Rights Reserved.
//
//  NOTICE: Microsoft Confidential. Intended for Internal Use Only.
//
////////////////////////////////////////////////////////////////////////////////

package com.msn.beet.loaders
{

import com.msn.beet.events.AssetTotalBytesEvent;

import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;

/**
 * Leaf node of asset loading composite system; downloads data from a URL as
 * text, binary data, or URL-encoded variables.
 *
 */
public class URLLoaderItem extends AbstractLoader
{
    include "../core/Version.as";

    private var _url:String;
    private var _bytesTotal:uint;

    private var _loader:URLLoader;
    private function get loader():URLLoader
    {
        return _loader || (_loader = createLoader());
    }

    public function URLLoaderItem(url:String, bytesTotal:uint = 0)
    {
        super(this);
        _url = url;
        _bytesTotal = bytesTotal;
    }

    protected function createLoader():URLLoader
    {
        return new URLLoader();
    }

    /**
     * Begins the load
     */
    override public function start():void
    {
        addLoaderListeners();
        this.loader.load(new URLRequest(_url));
    }

    /**
     * Stops the load
     */
    override public function stop():void
    {
        removeLoaderListeners();
        this.loader.close();
    }

    /**
     * Returns the untyped content of the loader
     *
     * @return
     */
    override public function get content():*
    {
        return this.loader.data;
    }

    /**
    * Return the url to load
    *
    * @return String url
    */
    override public function get url():String
    {
        return _url;
    }

    private function dispatchEventAndRemoveListeners(event:Event):void
    {
        dispatchEvent(event);
        removeLoaderListeners();
    }

    private function loader_progressHandler(event:ProgressEvent):void
    {
        if (event.bytesTotal != _bytesTotal)
        {
            _bytesTotal = event.bytesTotal;
            var assetEvent:AssetTotalBytesEvent =
                new AssetTotalBytesEvent(AssetTotalBytesEvent.CHANGE,
                                         _bytesTotal)
            dispatchEvent(assetEvent);
        }
        dispatchEvent(event);
    }

    private function loader_startHandler(event:Event):void
    {
        dispatchEvent(event);
    }

    private function loader_completeHandler(event:Event):void
    {
        dispatchEventAndRemoveListeners(event);
    }

    private function loader_errorHandler(event:Event):void
    {
        dispatchEventAndRemoveListeners(event);
    }

    private function addLoaderListeners():void
    {
        this.loader.addEventListener(Event.COMPLETE, loader_completeHandler);
        this.loader.addEventListener(Event.INIT, loader_startHandler);
        this.loader.addEventListener(ProgressEvent.PROGRESS,
                                     loader_progressHandler);
        this.loader.addEventListener(IOErrorEvent.IO_ERROR,
                                     loader_errorHandler);
        this.loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
                                     loader_errorHandler);
        this.loader.addEventListener(IOErrorEvent.NETWORK_ERROR,
                                     loader_errorHandler);
        this.loader.addEventListener(IOErrorEvent.DISK_ERROR,
                                     loader_errorHandler);
        this.loader.addEventListener(IOErrorEvent.VERIFY_ERROR,
                                     loader_errorHandler);
    }

    private function removeLoaderListeners():void
    {
        this.loader.removeEventListener(Event.COMPLETE, loader_completeHandler);
        this.loader.removeEventListener(Event.INIT, loader_startHandler);
        this.loader.removeEventListener(ProgressEvent.PROGRESS,
                                        loader_progressHandler);
        this.loader.removeEventListener(IOErrorEvent.IO_ERROR,
                                        loader_errorHandler);
        this.loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,
                                        loader_errorHandler);
        this.loader.removeEventListener(IOErrorEvent.NETWORK_ERROR,
                                        loader_errorHandler);
        this.loader.removeEventListener(IOErrorEvent.DISK_ERROR,
                                        loader_errorHandler);
        this.loader.removeEventListener(IOErrorEvent.VERIFY_ERROR,
                                        loader_errorHandler);
    }

    /**
     * Returns the total bytes of all children
     * @return
     */
    override public function get bytesTotal():uint
    {
        return _bytesTotal;
    }

    /**
     * Returns the total bytes loaded of all children
     * @return
     */
    override public function get bytesLoaded():uint
    {
        return this.loader.bytesLoaded;
    }
}

}
